import { useParams } from "react-router-dom";
import { useEffect, useState } from "react";
import { codeErrorAPI } from "../../apis/error";
import { List, Space, Typography } from 'antd';
import mStl from './code-error-detail.mod.less';
import { ReloadOutlined } from '@ant-design/icons';
import { Tabs } from 'antd';
import ColumnItem, { ColumnItemProp } from "./common/column-item";
import chromeIcon from "./img/chrome.f836b32e.svg";
import iosIcon from './img/ios.9af0022e.svg'
import moment from 'moment';
import { fmtIpAddress, getDevice } from '../../utils/index';

const {TabPane} = Tabs;

const CodeErrorDetail = () => {
  const {id} = useParams<{id: string}>();
  const [list, setList] = useState([]);
  const [curEvent, setCurEvent] = useState<any>(null);

  useEffect(() => {
    codeErrorAPI.findListByErrorMessage({
      searchKey: decodeURIComponent(id)
    }).then((res: any) => {
      if (res && res.success) {
        const list = res.data.list;
        setList(list);
        if (list.length) {
          setCurEvent(list[0])
        }
      }
    })
  }, [])

  if (!curEvent) {
    return <span>loading...</span>
  }


  const metadata = JSON.parse(curEvent.metadata);
  const device = getDevice(metadata.request["User-Agent"]);

  const detail = curEvent;
  const isStack = detail.type !== "resource" && detail.type !== "unhandledrejection";

  // 堆栈信息
  let stackFrames = [];
  if (isStack) {
    stackFrames = metadata.exception.stacktrace.frames;
    stackFrames = stackFrames.map((item: any) => {
      return (
        <div className={ "ui-text-gray" } style={ {fontSize: 13} }>
            <span>
              At { item['function'] || "?" } { item.filename }:{
              item.lineno
            }:{ item.colno }</span>
        </div>
      )
    })
  }

  function rendSideItem(item: any) {
    const cls = ['ui-pointer'];
    if (item === curEvent) {
      cls.push("is-active");
    }

    return (
      <List.Item className={ cls.join(" ") }>
        <div className={ mStl.item } onClick={ () => setCurEvent(item) }>
          <div className={ "ui-fs-small ui-text-gray" }>
            { fmtIpAddress(item.ip) }
          </div>
          <div className={ "ui-flex" }>
            <div className={ "icons" }>
              <img style={ {marginBottom: 3, marginRight: 2} } width={ 14 } src={ iosIcon } alt=""/>
              <img style={ {marginBottom: 1} } width={ 12 } src={ chromeIcon } alt=""/>
            </div>
            <div className="ui-fs-small ui-text-gray">
              <span>广东</span>
              <span>16 小时前</span>
            </div>
          </div>
        </div>
      </List.Item>
    )
  }

  return (
    <div className={ mStl.wrapper }>
      <div className={ mStl.side }>
        <List
          header={ <div className={ mStl.header }>
            <Space>
              <ReloadOutlined/>
              <span>事件列表</span>
            </Space>
          </div> }
          dataSource={ list }
          renderItem={ rendSideItem }
        />
      </div>
      <div className={ mStl.main }>
        <Tabs defaultActiveKey="1">
          <TabPane tab="基本信息" key="1">
            <div style={ {display: "flex"} }>
              <div style={ {flex: 1} }>
                <RenderCard title={ "概要信息" } columns={ summaryInfo(curEvent) }/>
                { isStack && <RenderCard title={ "堆栈信息" }>{ stackFrames }</RenderCard> }
                <RenderCard title={ "错误信息" } columns={
                  isStack
                    ? getValues(detail, errorSpecList())
                    : getValues(detail, errorList())
                }/>
              </div>
              <div style={ {
                width: 400,
                borderLeft: "1px solid #eee"
              } }>
                <RenderCard title={ "设备信息" } columns={ deviceInfo(device) }/>
                <RenderCard title={ "其他信息" } columns={ otherInfo() }/>
              </div>
            </div>
          </TabPane>
          <TabPane tab="元数据" key="2">
            <pre className={ mStl.json }>
              <code className="json-code">
                { JSON.stringify(JSON.parse(detail['metadata'] || "{}"), null, 2) }
              </code>
            </pre>
          </TabPane>
        </Tabs>
      </div>
    </div>
  )
}

function summaryInfo(detail: any) {
  return [
    {
      label: "时间",
      content: moment(+detail.time).format("YYYY-MM-DD")
    },
    {
      label: "类型",
      content: detail.type
    },
    {
      label: "地址",
      content: detail.page_url
    }
  ]
}

function deviceInfo(device: any) {
  return [
    {
      label: "浏览器",
      content: device.browser
    },
    {
      label: "JS引擎",
      content: device.jsEngine
    },
    {
      label: "操作系统",
      content: device.os
    }
  ]
}

function otherInfo() {
  return [
    {
      label: "插件版本",
      content: "--"
    },
    {
      label: "事件ID",
      content: "--"
    },
    {
      label: "UserAgent",
      content: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.106 Safari/537.36"
    }
  ]
}

interface RenderCardProp {
  title: string;
  columns?: ColumnItemProp[];
  children?: any;
}

function RenderCard(props: RenderCardProp) {
  return (
    <div style={ {
      padding: "20px",
      paddingBottom: 0
    }
    }>
      <div style={ {fontSize: 16, marginBottom: 16} }>{ props.title }</div>
      { props.children ? props.children : null }
      {
        props.columns && props.columns.map(it => {
          return (
            <ColumnItem label={ it.label } content={ it.content }/>
          )
        })
      }
    </div>
  )
}

function getValues(detail: any, columns: any[]) {
  return columns.map((it: any) => {
    return {
      label: it.title,
      content: detail[it.prop] || '--'
    }
  })
}

function errorSpecList() {
  return [
    {title: "名称", prop: "type"},
    {title: "信息", prop: "message"},
    {title: "文件", prop: "file"},
    {title: "行号", prop: "row"},
    {title: "列号", prop: "col"}
  ]
}

function errorList() {
  return [
    {title: "名称", prop: "type"},
    {title: "信息", prop: "message"}
  ]
}

export default CodeErrorDetail;
